This patch is to remove the pit_timer when the vmx domain is
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 5 Nov 2005 10:26:29 +0000 (11:26 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 5 Nov 2005 10:26:29 +0000 (11:26 +0100)
inactive to save HV external IRQ caused by ac_time and some cleanup for
ioapic in HV.
Thx,eddie

Signed-off-by: Eddie Dong <eddie.dong@intel.com>
15 files changed:
tools/ioemu/hw/pc.c
tools/ioemu/target-i386-dm/Makefile
tools/ioemu/target-i386-dm/helper2.c
xen/arch/x86/dm/i8259.c
xen/arch/x86/vmx.c
xen/arch/x86/vmx_intercept.c
xen/arch/x86/vmx_io.c
xen/arch/x86/vmx_vlapic.c
xen/arch/x86/vmx_vmcs.c
xen/include/asm-x86/vmx.h
xen/include/asm-x86/vmx_virpit.h
xen/include/asm-x86/vmx_vlapic.h
xen/include/asm-x86/vmx_vmcs.h
xen/include/public/io/vmx_vlapic.h
xen/include/public/io/vmx_vpic.h

index 97db4aaa94e221c16d856828bb50ddd85f95fcba..5de75550452f909e85cd76bd0eb37dced10f12e4 100644 (file)
@@ -547,9 +547,6 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device,
                 pci_pcnet_init(pci_bus, &nd_table[i]); 
         }
         pci_piix3_ide_init(pci_bus, bs_table);
-#ifdef APIC_SUPPORT
-        IOAPICInit();
-#endif
     } else {
         nb_nics1 = nb_nics;
         if (nb_nics1 > NE2000_NB_MAX)
index b97103486b2316e568e22037f8cfc5c48a54fbee..c05013f75cab1c45a94be693e48268801c53baa2 100644 (file)
@@ -187,7 +187,7 @@ endif
 
 #########################################################
 
-DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DAPIC_SUPPORT
+DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
 LIBS+=-lm -L../../libxc -lxenctrl
 ifndef CONFIG_USER_ONLY
 LIBS+=-lz
@@ -245,7 +245,6 @@ endif
 # must use static linking to avoid leaving stuff in virtual address space
 VL_OBJS=vl.o exec.o monitor.o osdep.o block.o readline.o pci.o console.o 
 VL_OBJS+=block-cow.o block-qcow.o block-vmdk.o block-cloop.o aes.o
-VL_OBJS+=ioapic.o
 #VL_OBJS+= block-cloop.o
 
 SOUND_HW = sb16.o
index c8039b42d091b73e3cafea6c289ca6ae935b7b31..6a9726271550b60abb8b8af4741fcb3d6cb89050 100644 (file)
@@ -456,17 +456,10 @@ int main_loop(void)
 #endif
 
                main_loop_wait(0);
-#ifdef APIC_SUPPORT
-               ioapic_update_EOI();
-#endif
         tun_receive_handler(&rfds);
         if ( FD_ISSET(evtchn_fd, &rfds) ) {
             cpu_handle_ioreq(env);
         }
-#ifdef APIC_SUPPORT
-               if (ioapic_has_intr())
-                    do_ioapic();
-#endif
                if (env->send_event) {
                        struct ioctl_evtchn_notify notify;
                        notify.port = ioreq_local_port;
index ed3ffc8eafef06185d4f4274184cdaf93fccfbf2..7d859f875ed7c6c275b1ad74bfa005ebbeb4cce5 100644 (file)
@@ -525,3 +525,16 @@ int is_pit_irq(struct vcpu *v, int irq, int type)
 
     return (irq == pit_vec);
 }
+
+int is_irq_enabled(struct vcpu *v, int irq)
+{
+    struct vmx_virpic *vpic=&v->domain->arch.vmx_platform.vmx_pic;
+        
+    if ( irq & 8 ) {
+        return !( (1 << (irq&7)) & vpic->pics[1].imr);
+    }
+    else {
+        return !( (1 << irq) & vpic->pics[0].imr);
+    }
+}
+
index a7ba1fb3ce4710ec4d91683adfb3c9877713a41f..fdf3423184f516c51ebe89eaffa49d93140d115c 100644 (file)
@@ -43,6 +43,8 @@
 #endif
 #include <public/sched.h>
 #include <public/io/ioreq.h>
+#include <public/io/vmx_vpic.h>
+#include <public/io/vmx_vlapic.h>
 
 int hvm_enabled;
 
@@ -85,6 +87,8 @@ void vmx_final_setup_guest(struct vcpu *v)
 
 void vmx_relinquish_resources(struct vcpu *v)
 {
+    struct vmx_virpit *vpit;
+    
     if ( !VMX_DOMAIN(v) )
         return;
 
@@ -96,7 +100,12 @@ void vmx_relinquish_resources(struct vcpu *v)
 
     destroy_vmcs(&v->arch.arch_vmx);
     free_monitor_pagetable(v);
-    rem_ac_timer(&v->domain->arch.vmx_platform.vmx_pit.pit_timer);
+    vpit = &v->domain->arch.vmx_platform.vmx_pit;
+    if ( vpit->ticking && active_ac_timer(&(vpit->pit_timer)) )
+        rem_ac_timer(&vpit->pit_timer);
+    if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) ) {
+        rem_ac_timer(&v->arch.arch_vmx.hlt_timer);
+    }
     if ( vmx_apic_support(v->domain) ) {
         rem_ac_timer( &(VLAPIC(v)->vlapic_timer) );
         xfree( VLAPIC(v) );
@@ -1521,12 +1530,24 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
                 (unsigned long)regs->edx);
 }
 
-volatile unsigned long do_hlt_count;
 /*
  * Need to use this exit to reschedule
  */
 void vmx_vmexit_do_hlt(void)
 {
+    struct vcpu *v=current;
+    struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
+    s_time_t   next_pit=-1,next_wakeup;
+
+    if ( !v->vcpu_id ) {
+        next_pit = get_pit_scheduled(v,vpit);
+    }
+    next_wakeup = get_apictime_scheduled(v);
+    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) {
+        next_wakeup = next_pit;
+    }
+    if ( next_wakeup != - 1 ) 
+        set_ac_timer(&current->arch.arch_vmx.hlt_timer, next_wakeup);
     do_block();
 }
 
index c21ad44fdb248802c3e2e121e1e0029cc154d9a1..d452f7b792166c72ceb77ec429b83113b324b333 100644 (file)
@@ -317,27 +317,51 @@ int intercept_pit_io(ioreq_t *p)
     return 0;
 }
 
-/* hooks function for the PIT initialization response iopacket */
-static void pit_timer_fn(void *data)
+/* hooks function for the HLT instruction emulation wakeup */
+void hlt_timer_fn(void *data)
+{
+    struct vcpu *v = data;
+    
+    evtchn_set_pending(v, iopacket_port(v->domain));
+}
+
+static __inline__ void missed_ticks(struct vmx_virpit*vpit)
 {
-    struct vmx_virpit *vpit = data;
-    s_time_t   next;
     int        missed_ticks;
 
     missed_ticks = (NOW() - vpit->scheduled)/(s_time_t) vpit->period;
-
-    /* Set the pending intr bit, and send evtchn notification to myself. */
-    vpit->pending_intr_nr++; /* already set, then count the pending intr */
-    evtchn_set_pending(vpit->v, iopacket_port(vpit->v->domain));
-
-    /* pick up missed timer tick */
     if ( missed_ticks > 0 ) {
         vpit->pending_intr_nr += missed_ticks;
         vpit->scheduled += missed_ticks * vpit->period;
     }
-    next = vpit->scheduled + vpit->period;
-    set_ac_timer(&vpit->pit_timer, next);
-    vpit->scheduled = next;
+}
+
+/* hooks function for the PIT when the guest is active */
+static void pit_timer_fn(void *data)
+{
+    struct vcpu *v = data;
+    struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
+
+    /* pick up missed timer tick */
+    missed_ticks(vpit);
+
+    vpit->pending_intr_nr++;
+    if ( test_bit(_VCPUF_running, &v->vcpu_flags) ) {
+        vpit->scheduled += vpit->period;
+        set_ac_timer(&vpit->pit_timer, vpit->scheduled);
+    }
+}
+
+void pickup_deactive_ticks(struct vmx_virpit *vpit)
+{
+
+    if ( !active_ac_timer(&(vpit->pit_timer)) ) {
+        /* pick up missed timer tick */
+        missed_ticks(vpit);
+    
+        vpit->scheduled += vpit->period;
+        set_ac_timer(&vpit->pit_timer, vpit->scheduled);
+    }
 }
 
 /* Only some PIT operations such as load init counter need a hypervisor hook.
@@ -359,8 +383,10 @@ void vmx_hooks_assist(struct vcpu *v)
             reinit = 1;
  
         }
-        else
-            init_ac_timer(&vpit->pit_timer, pit_timer_fn, vpit, v->processor);
+        else {
+            init_ac_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor);
+            vpit->ticking = 1;
+        }
 
         /* init count for this channel */
         vpit->init_val = (p->u.data & 0xFFFF) ;
@@ -397,8 +423,6 @@ void vmx_hooks_assist(struct vcpu *v)
             break;
         }
 
-        vpit->v = v;
-
         vpit->scheduled = NOW() + vpit->period;
         set_ac_timer(&vpit->pit_timer, vpit->scheduled);
 
index 33d4c7290c73acfdb512be0f0ffb59fd6f1d25aa..5b879bd52e2c26092f53e8804b9e6e98871cd9c6 100644 (file)
@@ -931,6 +931,7 @@ asmlinkage void vmx_intr_assist(void)
 
 void vmx_do_resume(struct vcpu *v)
 {
+    struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
     vmx_stts();
 
     if (event_pending(v)) {
@@ -939,6 +940,9 @@ void vmx_do_resume(struct vcpu *v)
         if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
             vmx_wait_io();
     }
+    /* pick up the elapsed PIT ticks and re-enable pit_timer */
+    if ( vpit->ticking )
+        pickup_deactive_ticks(vpit);
 
     /* We can't resume the guest if we're waiting on I/O */
     ASSERT(!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags));
index 80f372f282b3e7013c6494e4fdb65342a6b1cd15..4d45fcd3e6ee88948e3f9479ba29b032a68af6ac 100644 (file)
@@ -60,11 +60,20 @@ int vlapic_find_highest_irr(struct vlapic *vlapic)
     return result;
 }
 
-inline int vmx_apic_support(struct domain *d)
+int vmx_apic_support(struct domain *d)
 {
     return d->arch.vmx_platform.lapic_enable;
 }
 
+s_time_t get_apictime_scheduled(struct vcpu *v)
+{
+    struct vlapic *vlapic = VLAPIC(v);
+
+    if ( !vmx_apic_support(v->domain) || !vlapic_lvt_timer_enabled(vlapic) )
+        return -1;
+    return vlapic->vlapic_timer.expires;
+}
+
 int vlapic_find_highest_isr(struct vlapic *vlapic)
 {
     int result;
index 97d66e2ef7d2298c270f03b33aa8127157b97729..abf3684160938b63378677fc9d88edd5a43ac51a 100644 (file)
@@ -321,6 +321,7 @@ static void vmx_do_launch(struct vcpu *v)
         vlapic_init(v);
 
     vmx_set_host_env(v);
+    init_ac_timer(&v->arch.arch_vmx.hlt_timer, hlt_timer_fn, v, v->processor);
 
     error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
     error |= __vmwrite(GUEST_LDTR_BASE, 0);
index 445c24bb592248a9b2efaeed103c1cb99f2f84de..771ac68ef4942c5c2f5d8be828c6e3f7a658597c 100644 (file)
@@ -530,5 +530,6 @@ void store_cpu_user_regs(struct cpu_user_regs *regs);
 
 enum { VMX_COPY_IN = 0, VMX_COPY_OUT };
 int vmx_copy(void *buf, unsigned long laddr, int size, int dir);
+void pickup_deactive_ticks(struct vmx_virpit *vpit);
 
 #endif /* __ASM_X86_VMX_H__ */
index 9539682d940dd703bb7f5f79a040d4ea763d16c6..fad07a98470efb3d7343ab78b3023cd3e31d44d0 100644 (file)
@@ -8,6 +8,7 @@
 #include <xen/errno.h>
 #include <xen/ac_timer.h>
 #include <asm/vmx_vmcs.h>
+#include <public/io/vmx_vpic.h>
 
 #define PIT_FREQ 1193181
 
 
 struct vmx_virpit {
     /* for simulation of counter 0 in mode 2*/
-    u32 period;                /* pit frequency in ns */
     u64 period_cycles;                 /* pit frequency in cpu cycles */
+    u64 inject_point; /* the time inject virt intr */
     s_time_t scheduled;                 /* scheduled timer interrupt */
+    struct ac_timer pit_timer;  /* periodic timer for mode 2*/
     unsigned int channel;  /* the pit channel, counter 0~2 */
     unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
-    u64 inject_point; /* the time inject virt intr */
-    struct ac_timer pit_timer;  /* periodic timer for mode 2*/
+    u32 period;                /* pit frequency in ns */
     int first_injected;                 /* flag to prevent shadow window */
+    int ticking;    /* indicating it is ticking */
 
     /* virtual PIT state for handle related I/O */
     int read_state;
@@ -34,10 +36,20 @@ struct vmx_virpit {
 
     unsigned int count;  /* the 16 bit channel count */
     unsigned int init_val; /* the init value for the counter */
-    struct vcpu *v;
 };
 
 /* to hook the ioreq packet to get the PIT initializaiton info */
 extern void vmx_hooks_assist(struct vcpu *v);
 
+static __inline__ s_time_t get_pit_scheduled(
+    struct vcpu *v, 
+    struct vmx_virpit *vpit)
+{
+    if ( is_irq_enabled(v, 0) ) {
+        return vpit->scheduled;
+    }
+    else
+        return -1;
+}
+
 #endif /* _VMX_VIRPIT_H_ */
index 53dee225b4347bc43331b524fef221d936eb0a3d..c8b4dde3a7c2b6da5dba7aa9ac6d08954c681d98 100644 (file)
@@ -239,7 +239,8 @@ struct vlapic* apic_round_robin(struct domain *d,
                                 uint8_t dest_mode,
                                 uint8_t vector,
                                 uint32_t bitmap);
-
+s_time_t get_apictime_scheduled(struct vcpu *v);
 int vmx_apic_support(struct domain *d);
 
 #endif /* VMX_VLAPIC_H */
+
index 2d366ef7a556b08965abcc10c3a3fb01566fc947..769fe555bb46a0d85f45db86722adc5abdfe98c3 100644 (file)
@@ -99,6 +99,7 @@ struct arch_vmx_struct {
     void                    *io_bitmap_a, *io_bitmap_b;
     struct vlapic           *vlapic;
     u64                     tsc_offset;
+    struct ac_timer         hlt_timer;  /* hlt ins emulation wakeup timer */
 };
 
 #define vmx_schedule_tail(next)         \
@@ -116,6 +117,7 @@ struct vmcs_struct *alloc_vmcs(void);
 int modify_vmcs(struct arch_vmx_struct *arch_vmx,
                 struct cpu_user_regs *regs);
 void destroy_vmcs(struct arch_vmx_struct *arch_vmx);
+void hlt_timer_fn(void *data);
 
 #define VMCS_USE_HOST_ENV       1
 #define VMCS_USE_SEPARATE_ENV   0
index 5a8162b2e1d47c4582afeb4e3cacb2833f86457a..f63a9aaf16a86063e17500c69f6c6ff8587fd6e4 100644 (file)
 #define VLAPIC_INT_COUNT                (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(uint64_t)))
 #define VLAPIC_INT_COUNT_32             (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(uint32_t)))
 
-struct vapic_bus_message{
-   uint8_t   deliv_mode:4;   /* deliver mode, including fixed, LPRI, etc */
-   uint8_t   level:1;        /* level or edge */
-   uint8_t   trig_mod:1;    /* assert or disassert */
-   uint8_t   reserved:2;
-   uint8_t   vector;
-};
-
 typedef struct {
     /* interrupt for PIC and ext type IOAPIC interrupt */
     uint64_t   vl_ext_intr[VLAPIC_INT_COUNT];
@@ -51,7 +43,6 @@ typedef struct {
     uint32_t   vl_arb_id;
     uint32_t   vl_state;
     uint32_t   apic_msg_count;
-    struct vapic_bus_message  vl_apic_msg[24];
 } vlapic_info;
 
 #endif /* _VMX_VLAPIC_H_ */
index e567c6340094f74f6eabb46e9bdf8cecb5132d74..256ac87ec57214e37ea971f397d78a30e3719bbd 100644 (file)
@@ -77,6 +77,7 @@ uint32_t pic_intack_read(struct vmx_virpic *s);
 void register_pic_io_hook (void);
 int cpu_get_pic_interrupt(struct vcpu *v, int *type);
 int is_pit_irq(struct vcpu *v, int irq, int type);
+int is_irq_enabled(struct vcpu *v, int irq);
 void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
 void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);